package cn.jiyun.service.impl;

import cn.jiyun.pojo.DTO.OrdersDto;
import cn.jiyun.mapper.OrdersMapper;
import cn.jiyun.pojo.MassagerTousu;
import cn.jiyun.pojo.cokpit.Orders;
import cn.jiyun.pojo.function.BackstageCount;
import cn.jiyun.service.OrdersService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import static cn.jiyun.util.BoxWhiskerTool.getTime;
import static cn.jiyun.util.BoxWhiskerTool.plot;

/**
 * 订单表(Orders)表服务实现类
 *
 * @author makejava
 * @since 2024-12-20 09:38:33
 */
@Service("ordersService")
@Slf4j
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements OrdersService {
    @Resource
    private OrdersMapper ordersMapper;

    @Override
    public Integer getUnansweredOrders() {
        return ordersMapper.getUnansweredOrders();
    }

    @Override
    public Integer getOrderComplete() {

        // 今天订单总数
        Integer orderTotal = ordersMapper.getOrderTotal();

        // 今天订单完成数
        Integer orderComplete = ordersMapper.getOrderComplete();

        if (orderTotal == 0) {
            return 0;
        }

        //求百分比
        int percent = orderComplete / orderTotal * 100;
        return percent;
    }

    @Override
    public List<Integer> getDataMorning() {
        return ordersMapper.getDataMorning();
    }

    @Override
    public List<Integer> getDataAfternoon() {
        return ordersMapper.getDataAfternoon();
    }

    @Override
    public Integer getData() {
        return ordersMapper.getOrderTotal();
    }

    @Override
    public List<String> getDatesInRange(OrdersDto ordersDto) {
        return ordersMapper.getDatesInRange(ordersDto);
    }

    @Override
    public List<String> getOrderCountsInRange(OrdersDto ordersDto) {

        List<Orders> list = ordersMapper.findAllList();
        List<Orders> orders = ordersMapper.selectList(null);

        Integer orderTotal;
        if (ordersDto.getStartTime() != null && ordersDto.getEndTime() != null) {
            orderTotal = ordersMapper.getOrderTotal();
        } else {
            orderTotal = list.size();
        }

        return ordersMapper.getOrderCountsInRange(ordersDto);
    }

    @Override
    public List<String> getOrderCountsInRange2(OrdersDto ordersDto) {
        return ordersMapper.getOrderCountsInRange2(ordersDto);
    }

    @Override
    public BigDecimal getInflow() {
        return ordersMapper.getInflow();
    }

    @Override
    public List<BigDecimal> getTotalAmountInRange(OrdersDto ordersDto) {
        return ordersMapper.getTotalAmountInRange(ordersDto);
    }

    @Override
    public List<BigDecimal> getTotalDriverEarningsInRange(OrdersDto ordersDto) {


        return ordersMapper.getTotalDriverEarningsInRange(ordersDto);
    }

    @Override
    public List<BigDecimal> getTheTotalWriteOffAmountWithinTheRange(OrdersDto ordersDto) {
        return ordersMapper.getTheTotalWriteOffAmountWithinTheRange(ordersDto);
    }

    @Override
    public List<BigDecimal> getEarningsAmount(OrdersDto ordersDto) {
        return ordersMapper.getEarningsAmount(ordersDto);
    }

    @Override
    public List<BigDecimal> getAvgTotalAmount(OrdersDto ordersDto) {
        return ordersMapper.getAvgTotalAmount(ordersDto);
    }

    @Override
    public List<BigDecimal> getAvgDriverIncome(OrdersDto ordersDto) {
        return ordersMapper.getAvgDriverIncome(ordersDto);
    }

    @Override
    public List<BigDecimal> getTotalCancelMoney(OrdersDto ordersDto) {
        return ordersMapper.getTotalCancelMoney(ordersDto);
    }

    @Override
    public List<BigDecimal> getAvgEarnings(OrdersDto ordersDto) {
        return ordersMapper.getAvgEarnings(ordersDto);
    }

    /**
     * 获取登录统计信息
     * 此方法根据订单DTO获取用户的登录统计信息和订单统计信息，并计算每个统计时间段内的平均值
     * 主要目的是分析用户登录行为与订单数量之间的关系
     *
     * @param ordersDto 订单DTO对象，包含查询条件和参数
     * @return 返回一个整数列表，包含每个统计时间段内订单数量与登录用户数的平均值
     */
    @Override
    public List<Integer> getLoginStatistics(OrdersDto ordersDto) {
        // 获取登录统计信息
        List<Integer> loginStatistics = ordersMapper.getLoginStatistics(ordersDto);
        // 获取特定范围内的订单统计信息
        List<String> countsInRange2 = ordersMapper.getOrderCountsInRange2(ordersDto);
        // 创建一个整数列表存储计算结果
        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        // 遍历登录统计信息
        for (int i = 0; i < loginStatistics.size(); i++) {
            // 如果登录用户数为0，则直接添加0到结果列表中
            if (loginStatistics.get(i) == 0) {
                arrayList.add(0);
                // 跳过本次循环
                continue;
            }
            // 计算并添加订单数量与登录用户数的平均值到结果列表中
            arrayList.add(Integer.parseInt(countsInRange2.get(i)) / loginStatistics.get(i));
        }
        // 记录日志信息
        log.info("arrayList:{}", arrayList);
        // 返回计算结果
        return arrayList;
    }

    /**
     * 计算人均司机收入
     *
     * @param ordersDto 订单DTO，包含用于查询的参数
     * @return 返回一个BigDecimal列表，包含每个时间段的人均司机收入
     */
    @Override
    public List<BigDecimal> getPerCapitaIncome(OrdersDto ordersDto) {
        // 获取今日司机登录数量
        List<Integer> loginStatistics = ordersMapper.getLoginStatistics(ordersDto);
        // 获取今日所有司机收入总金额
        List<BigDecimal> earningsInRange = ordersMapper.getTotalDriverEarningsInRange(ordersDto);
        // 存放司机收入总金额/司机登录数量=人均收益
        List<BigDecimal> arrayList = new ArrayList<BigDecimal>();

        for (int i = 0; i < loginStatistics.size(); i++) {
            // 如果司机登录数量为0，则将人均收益设置为0
            if (loginStatistics.get(i) == 0) {
                arrayList.add(BigDecimal.valueOf(0.00));
                //跳过本次循环
                continue;
            }
            //
            BigDecimal bigDecimal = earningsInRange.get(i);
            // 计算人均收益，使用四舍五入模式
            BigDecimal divide = bigDecimal.divide(bigDecimal.valueOf(loginStatistics.get(i)), RoundingMode.HALF_UP);
            arrayList.add(divide);
        }
        // 记录日志，输出人均收益列表
        log.info("arrayList:{}", arrayList);
        // 返回人均收益列表
        return arrayList;
    }

    /**
     * 获取总收入
     * 该方法用于获取所有订单的总收入情况
     * 它通过调用ordersMapper的getEarnings方法来实现
     *
     * @return BigDecimal 返回总收入金额，使用BigDecimal以确保财务计算的精确性
     */
    @Override
    public Double getEarnings() {
        return ordersMapper.getEarnings();
    }

    @Override
    public Double getComplaint() {
        // 获取投诉总数量
        List<MassagerTousu> complaint = ordersMapper.getComplaint();
        Integer count = 0;
        log.info("complaint:{}", complaint);
        for (MassagerTousu massagerTousu : complaint) {
            if (massagerTousu.getAppealStatus() == 1) {
                System.err.println("count");
                count += 1;
            }
        }
        log.info("count:{}", count);
        //求百分比count为0则返回0
        if (complaint.size() == 0 || count == 0) {
            return 0.0;
        }

        Double v = count * 100.0 / complaint.size();
        return v;
    }

    @Override
    public List<String> findDateAll() {
        List<String> dateAll = ordersMapper.findDateAll();
        log.info("dateAll:{}", dateAll);
        return null;
    }

    /**
     * 重写getBoxWhiskerList方法，根据订单信息生成箱线图所需的数据列表
     *
     * @param ordersDto 订单的DTO对象，包含筛选条件
     * @return 返回一个ArrayList，包含多个List<Double>，每个List<Double>代表一个日期的数据
     * @throws ParseException 当日期解析出错时抛出此异常
     */
    @Override
    public ArrayList<List<Double>> getBoxWhiskerList(OrdersDto ordersDto) throws ParseException {
        // 获取指定条件下的所有订单列表
        List<Orders> dateAll = ordersMapper.findList(ordersDto);
        // 获取指定条件下的所有日期列表
        List<String> datesInRange = ordersMapper.getDatesInRange(ordersDto);
        // 创建一个HashMap，用于存储每个日期对应的数据
        HashMap<String, ArrayList<Long>> map = new HashMap<>();
        // 创建一个SimpleDateFormat对象，用于日期格式的转换
        SimpleDateFormat sdf = new SimpleDateFormat("MM/dd");
        // 遍历日期列表，筛选出每个日期的公司数据
        for (String date : datesInRange) {
            ArrayList<Long> integers = new ArrayList<>();
            for (Orders orders : dateAll) {
                // 将公司的起始日期转换为指定格式
                String format = sdf.format(orders.getStartingDate());
                // 如果转换后的日期与当前遍历的日期相符，计算该公司在该日期的数据并保存
                if (date.equals(format)) {
                    // 计算时间差，并将结果添加到当前日期对应的数据列表中
                    long time = getTime(orders.getStartingDate(), orders.getReceivingTime());
                    // 将计算出的时间值添加到整数列表中
                    integers.add(time);
                }
            }
            // 将筛选后的数据与日期关联，存入HashMap
            map.put(date, integers);
        }

        // 对日期列表进行排序
        datesInRange.sort(String::compareTo);
        // 输出排序后的日期列表
        System.err.println(datesInRange);
        // 创建一个ArrayList，用于存储最终的数据结果
        ArrayList<List<Double>> arrayLists = new ArrayList<>();
        // 遍历排序后的日期列表，计算并添加每个日期的数据到最终结果列表中
        for (String s : datesInRange) {
            ArrayList<Long> list = map.get(s);
            if (list != null) {
                // 根据每个日期的数据列表生成箱线图所需的数据结构，并添加到最终结果列表中
                List<Double> plot = plot(list);
                // 将plot对象添加到arrayLists集合中
                arrayLists.add(plot);
            }
        }
        // 记录最终的数据结果
        log.error(arrayLists.toString());
        // 返回最终的数据结果
        return arrayLists;
    }
}


